package com.hibase.core.interfacetask.util;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hibase.core.interfacetask.constant.TaskDealStatus;
import com.hibase.core.interfacetask.entity.MdsInterfaceTask;
import com.hibase.core.interfacetask.entity.MdsInterfaceType;
import com.hibase.core.interfacetask.service.IMdsInterfaceTaskService;
import com.hibase.core.interfacetask.service.MdsInterfaceTypeService;
import com.hibase.core.mq.component.HibaseQueueUtil;
import com.hibase.common.exception.HibaseAssert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * @author chenfeng
 * @version 1.0
 * @date 2021/9/10 15:14
 * @des https://gitee.com/cheershi
 */
@Component
@Slf4j
public class HibaseTaskUtil {

    @Autowired
    private IMdsInterfaceTaskService mdsInterfaceTaskService;

    @Autowired
    private MdsInterfaceTypeService mdsInterfaceTypeService;

    @Autowired
    private HibaseQueueUtil hibaseQueueUtil;

    /**
     * 增加任务
     *
     * @param topicName        queue的topic Name
     * @param bizId            业务单号
     * @param requestData      请求数据
     * @param responseData      返回数据
     * @param sender           发送者
     * @param receiver         接收者
     * @param businessTypeCode 业务类型Code
     * @param businessType     业务类型
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTask(String topicName,
                                    String bizId,
                                    String bizCode,
                                    String requestData,
                                    String responseData,
                                    String sender,
                                    String receiver,
                                    String businessTypeCode,
                                    String businessType) {
        MdsInterfaceTask task = new MdsInterfaceTask();
        task.setDealStatus(TaskDealStatus.TASK_DEAL_READY.getName());
        task.setBusinessId(bizId);
        task.setBusinessCode(bizCode);
        task.setRequestData(requestData);
        task.setResponseData(responseData);
        task.setSenderSys(sender);
        task.setReceiverSys(receiver);
        task.setBusinessType(businessType);
        task.setBusinessTypeCode(businessTypeCode);
        task.setRetryCount(0);
        task = mdsInterfaceTaskService.storeByNewTransactional(task);
        String taskId = task.getId();
        HibaseTaskUtil taskUtil = this;
        // 保证task保存之后 才发送消息 确保消费的时候一定有task
        TransactionSynchronizationManager.registerSynchronization(
                new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCommit() {
                        try {
                            hibaseQueueUtil.offer(topicName, taskId);
                        }catch (Exception e){
                            log.error("【Redis-Queue】 插入redis QUEUE 失败 {} | 数据 : {}",topicName,taskId);
                            taskUtil.taskFail(taskId,e.getMessage());
                        }
                    }
                }
        );
        return task;
    }

    /**
     * 增加任务
     *
     * @param topicName        queue的topic Name
     * @param bizId            业务单号
     * @param requestData      数据
     * @param sender           发送者
     * @param receiver         接收者
     * @param businessTypeCode 业务类型Code
     * @param businessType     业务类型
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTask(String topicName,
                                    String bizId,
                                    String bizCode,
                                    String requestData,
                                    String sender,
                                    String receiver,
                                    String businessTypeCode,
                                    String businessType) {
        return this.addTask(topicName,
                bizId,
                bizCode,
                requestData,
                null,
                sender,
                receiver,
                businessTypeCode,
                businessType);
    }

    /**
     * 增加任务
     *
     * @param topicName        queue的topic Name
     * @param bizId            业务单号
     * @param requestData      数据
     * @param sender           发送者
     * @param receiver         接收者
     * @param businessTypeCode 业务类型Code
     * @param businessType     业务类型
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTask(String topicName,
                                    String bizId,
                                    String requestData,
                                    String sender,
                                    String receiver,
                                    String businessTypeCode,
                                    String businessType) {
        return this.addTask(topicName,
                bizId,
                bizId,
                requestData,
                sender,
                receiver,
                businessTypeCode,
                businessType);
    }

    /**
     * 增加任务
     *
     * @param businessTypeCode 业务类型Code
     * @param bizId            业务类型id
     * @param bizCode          业务类型code
     * @param requestData      请求数据
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTask(String businessTypeCode,
                                    String bizId,
                                    String bizCode,
                                    String requestData) {
        return this.addTask(businessTypeCode,
                bizId,
                bizCode,
                requestData,
                null);
    }

    /**
     * 增加任务
     *
     * @param businessTypeCode 业务类型Code
     * @param bizId            业务类型id
     * @param bizCode          业务类型code
     * @param requestData      请求数据
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTask(String businessTypeCode,
                                    String bizId,
                                    String bizCode,
                                    String requestData,
                                    String responseData) {
        MdsInterfaceType type = mdsInterfaceTypeService.getOne(Wrappers.<MdsInterfaceType>lambdaQuery()
                .eq(MdsInterfaceType::getBusinessTypeCode, businessTypeCode)
                .eq(MdsInterfaceType::getBeActive, Boolean.TRUE)
        );
        HibaseAssert.notNull(type, "增加任务失败,请确认{}是否配置", businessTypeCode);
        return this.addTask(type.getTopicNameNormal(),
                bizId,
                bizCode,
                requestData,
                responseData,
                type.getSenderSys(),
                type.getReceiverSys(),
                businessTypeCode,
                type.getBusinessTypeName());
    }

    /**
     * 增加异常任务
     *
     * @param businessTypeCode 业务类型Code
     * @param bizId            业务类型id
     * @param bizCode          业务类型code
     * @param requestData      请求数据
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask addTaskByException(String businessTypeCode,
                                               String bizId,
                                               String bizCode,
                                               String requestData) {
        MdsInterfaceType type = mdsInterfaceTypeService.getOne(Wrappers.<MdsInterfaceType>lambdaQuery()
                .eq(MdsInterfaceType::getBusinessTypeCode, businessTypeCode)
                .eq(MdsInterfaceType::getBeActive, Boolean.TRUE)
        );
        HibaseAssert.notNull(type, "增加任务失败,请确认{}是否配置", businessTypeCode);
        return this.addTask(type.getTopicNameException(),
                bizId,
                bizCode,
                requestData,
                type.getSenderSys(),
                type.getReceiverSys(),
                businessTypeCode,
                type.getBusinessTypeName());
    }

    /**
     * 保存task
     *
     * @param task
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MdsInterfaceTask storeTask(MdsInterfaceTask task) {
        return mdsInterfaceTaskService.store(task);
    }

    public MdsInterfaceTask getTaskById(String id) {
        MdsInterfaceTask task = mdsInterfaceTaskService.getById(id, false);
        HibaseAssert.notNull(task, "未查询到Task任务，Task Id：{}", id);
        String businessTypeCode = task.getBusinessTypeCode();
        MdsInterfaceType taskType = mdsInterfaceTypeService.getOne(new QueryWrapper<MdsInterfaceType>().eq("business_type_code", businessTypeCode));
        task.setReceiverSysUrl(taskType != null ? taskType.getUrl() : "");
        return task;
    }

    @Transactional(rollbackFor = Exception.class)
    public void taskFail(String interfaceId, String msg) {
        MdsInterfaceTask task = this.getTaskById(interfaceId);
        // 设置任务状态为失败
        task.setDealStatus(TaskDealStatus.TASK_DEAL_FAIL.getName());
        task.setResponseData(msg);
        task.setExecTime(DateUtil.date());
        this.storeTask(task);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void taskSuccess(String interfaceId, String msg) {
    	MdsInterfaceTask task = this.getTaskById(interfaceId);
    	// 设置任务状态为完成
    	task.setDealStatus(TaskDealStatus.TASK_DEAL_SUCCESS.getName());
    	task.setResponseData(msg);
    	task.setExecTime(DateUtil.date());
    	this.storeTask(task);
    }

    @Transactional(rollbackFor = Exception.class)
    public void taskSuccess(String interfaceId) {
        MdsInterfaceTask task = this.getTaskById(interfaceId);
        // 设置任务状态为完成
        task.setDealStatus(TaskDealStatus.TASK_DEAL_SUCCESS.getName());
        task.setExecTime(DateUtil.date());
        this.storeTask(task);
    }
}
